package com.jxin.mall.sso.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.jxin.mall.entity.consts.HttpRspStatusEnum;
import com.jxin.mall.member.service.entity.dto.rsp.UserLoginRspDTO;
import com.jxin.mall.sso.properties.SSOProperties;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;


import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 基于Token的SSO过滤器
 * @author  蔡佳新
 * @version 1.0
 * @since   jdk 1.8
 */
@WebFilter(filterName = "ssoTokenFilter", urlPatterns = "/*")
@Data
public class SSOTokenFilter implements Filter {
    /**单点登入参数*/
    private SSOProperties ssoProperties;
    /**json返回参数模板*/
    private static final String RSP_JSON_TEMP = "\\{\"code\":{}, \"msg\":{}\\}";
    /**回调地址模板*/
    private static final String CALL_BACK_URL_TEMP = "?backUrl=";
    /**单点登入用户参数名*/
    private static final String SSO_USER_PARAM_NAME = "ssoUser";
    /**ant 表达式工具类*/
    private static final PathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse rsp = (HttpServletResponse) servletResponse;

        // 排除路径相关逻辑
        if (!CollectionUtils.isEmpty(getSsoProperties().getExcludedPaths())) {
            for (String excludedPath : getSsoProperties().getExcludedPaths()) {
                String uriPattern = excludedPath.trim();

                // 支持ANT表达式
                if (ANT_PATH_MATCHER.match(uriPattern, req.getServletPath())) {
                    // 被排除的路径无需到单点登入服务器确认
                    filterChain.doFilter(servletRequest, servletResponse);
                    return;
                }

            }
        }

        // logout filter
        if (StringUtils.isNoneBlank(getSsoProperties().getLogoutPath())
         && getSsoProperties().getLogoutPath().equals(req.getServletPath())) {
            // 所有服务端登出操作
            // SsoTokenLoginHelper.logout(req);

            // 响应登出成功
            rsp.setStatus(HttpRspStatusEnum.HTTP_RES_CODE_200.getCode());
            rsp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            rsp.getWriter().println(StrUtil.format(RSP_JSON_TEMP,
                                                   HttpRspStatusEnum.HTTP_RES_CODE_200.getCode(),
                                                   HttpRspStatusEnum.HTTP_RES_CODE_200.getName()));

            return;
        }

        // login filter
        UserLoginRspDTO memberUser = UserLoginRspDTO.builder().build();
        if (memberUser == null) {
            // 重定向到单点登入服务端
            rsp.sendRedirect(StrUtil.builder(getSsoProperties().getServerPath(),
                                             CALL_BACK_URL_TEMP,
                                             URLUtil.encodeAll(req.getServletPath()))
                             .toString());
            return;
        }

        // 往请求中放入用户实例
        servletRequest.setAttribute(SSO_USER_PARAM_NAME, memberUser);
        // 继续后续流程
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
